package com.tx.admin.lifeday.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.tx.admin.charartertag.pojo.dto.ChararterTagCreateDTO;
import com.tx.admin.charartertag.pojo.po.ChararterTag;
import com.tx.admin.charartertag.pojo.vo.ChararterTagVO;
import com.tx.admin.charartertag.service.ChararterTagService;
import com.tx.admin.lifeday.pojo.dto.*;
import com.tx.admin.lifeday.pojo.vo.LifeDayListVO;
import com.tx.admin.lifepicture.pojo.dto.LifePictureUpdateDTO;
import com.tx.admin.lifepicture.pojo.po.LifePicture;
import com.tx.admin.lifepicture.service.LifePictureService;
import com.tx.admin.tagrelate.pojo.po.TagRelate;
import com.tx.admin.tagrelate.service.TagRelateService;
import com.tx.core.common.entity.PageQuery;
import com.tx.core.util.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.tx.admin.lifeday.service.LifeDayService;
import com.tx.admin.lifeday.pojo.po.LifeDay;
import com.tx.admin.lifeday.mapper.LifeDayMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.tx.core.common.enums.CommonResponseEnum;
import com.tx.core.common.entity.PageResult;
import com.tx.core.common.entity.SelectIdsDTO;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.*;

import com.tx.core.common.entity.ImportExcelDTO;
import com.tx.excel.core.ExcelResult;
import java.io.OutputStream;
import java.util.function.Function;
import java.util.stream.Collectors;

import jakarta.servlet.http.HttpServletResponse;
import com.tx.excel.utils.ExcelUtils;
import lombok.SneakyThrows;
import com.tx.admin.lifeday.pojo.vo.LifeDayVO;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 生活记录每日表 服务实现类
 * </p>
 *
 * @author sz-admin
 * @since 2025-08-22
 */
@Service
@RequiredArgsConstructor
public class LifeDayServiceImpl extends ServiceImpl<LifeDayMapper, LifeDay> implements LifeDayService {

    @Autowired
    private ChararterTagService tagService;

    @Autowired
    private LifePictureService pictureService;

    @Autowired
    private TagRelateService tagRelateService;

    @Override
    public void create(LifeDayCreateDTO dto) {
        LifeDay lifeDay = BeanCopyUtils.copy(dto, LifeDay.class);
        save(lifeDay);
    }

    @Override
    public void update(LifeDayUpdateDTO dto) {
        LifeDay lifeDay = BeanCopyUtils.copy(dto, LifeDay.class);
        QueryWrapper wrapper;
        // id有效性校验
        wrapper = QueryWrapper.create()
                .eq(LifeDay::getId, dto.getId());
        CommonResponseEnum.INVALID_ID.assertTrue(count(wrapper) <= 0);

        saveOrUpdate(lifeDay);
    }

    @Override
    public PageResult<LifeDayVO> page(LifeDayListDTO dto) {
        Page<LifeDayVO> page = pageAs(PageUtils.getPage(dto), buildQueryWrapper(dto), LifeDayVO.class);
        return PageUtils.getPageResult(page);
    }

    @Override
    public List<LifeDayVO> list(LifeDayListDTO dto) {
        return listAs(buildQueryWrapper(dto), LifeDayVO.class);
    }

    @Override
    public void remove(SelectIdsDTO dto) {
        CommonResponseEnum.INVALID_ID.assertTrue(dto.getIds().isEmpty());
        removeByIds(dto.getIds());
    }

    @Override
    public LifeDayVO detail(Object id) {
        LifeDay lifeDay = getById((Serializable) id);
        CommonResponseEnum.INVALID_ID.assertNull(lifeDay);
        return BeanCopyUtils.copy(lifeDay, LifeDayVO.class);
    }

    @SneakyThrows
    @Override
    public void importExcel(ImportExcelDTO dto) {
        ExcelResult<LifeDayImportDTO> excelResult = ExcelUtils.importExcel(dto.getFile().getInputStream(), LifeDayImportDTO.class, true);
        List<LifeDayImportDTO> list = excelResult.getList();
        List<String> errorList = excelResult.getErrorList();
        String analysis = excelResult.getAnalysis();
        System.out.println(" analysis : " + analysis);
        System.out.println(" isCover : " + dto.getIsCover());
    }

    @SneakyThrows
    @Override
    public void exportExcel(LifeDayListDTO dto, HttpServletResponse response) {
        List<LifeDayVO> list = list(dto);
        String fileName = "生活记录每日表模板";
        OutputStream os = FileUtils.getOutputStream(response, fileName + ".xlsx");
        ExcelUtils.exportExcel(list, "生活记录每日表", LifeDayVO.class, os);
    }

    @Override
    @Transactional
    public Long createOneDay(LifeDayCreateDTO dto) {
        QueryWrapper wrapper = QueryWrapper.create().from(LifeDay.class);
        wrapper.eq(LifeDay::getCreateDay, LocalDate.now());
        if (CollUtil.isNotEmpty(list(wrapper))) {
            throw new IllegalStateException("今天的已经存在了");
        }

        LifeDay lifeDay = new LifeDay();
        //保存主体
        lifeDay.setId(Math.abs(UUID.randomUUID().getMostSignificantBits()));
        lifeDay.setCreateDay(LocalDate.now());
        lifeDay.setSki(dto.getSki());
        lifeDay.setHair(dto.getHair());
        lifeDay.setWeight(dto.getWeight());
        //ext1作为消费了
        lifeDay.setCost(dto.getCost());
        save(lifeDay);

        //近身
        LifePicture masterPicture1 =new LifePicture();
        masterPicture1.setBelongId(lifeDay.getId());
        masterPicture1.setPictureUrl(dto.getFaceUrl());
        masterPicture1.setType("0");
        //全身
        LifePicture masterPicture2 =new LifePicture();
        masterPicture2.setBelongId(lifeDay.getId());
        masterPicture2.setPictureUrl(dto.getWholeUrl());
        masterPicture2.setType("1");


        //提取没有ID的tag并判断是否存在冲突
        Set<String> desList = new HashSet<>();
        Map<String,Long> desIdMap = new HashMap<>();
        List<ChararterTag> newTags = dto.getSrcList().stream()
                .flatMap(s -> s.getItem().stream())
                .peek(s->{
                    if (Objects.isNull(s.getId())) {
                        return;
                    }
                    desIdMap.put(s.getDescribe(), s.getId());
                })
                .filter(s -> Objects.isNull(s.getId()))
                .map(s -> {
                    desList.add(s.getDescribe());
                    ChararterTag tag = new ChararterTag();
                    tag.setId(Math.abs(UUID.randomUUID().getMostSignificantBits()));
                    tag.setColor(s.getColor());
                    tag.setColorName(s.getColorName());
                    tag.setTagType("1");//按字典的
                    //tag.setRemark(s.getDescribe());
                    tag.setDescribe(s.getDescribe());
                    desIdMap.put(tag.getDescribe(), tag.getId());
                    return tag;
                })
                .toList();

        QueryWrapper tagWrapper = QueryWrapper.create().from(ChararterTag.class);
        tagWrapper.in(ChararterTag::getDescribe, desList).eq(ChararterTag::getTagType, "1");//1为生活记录
        if (CollUtil.isNotEmpty(desList)){
            //throw new IllegalStateException("新的标签重复了--" + newTags.stream().map(ChararterTag::getDescribe).collect(Collectors.joining(",")));
            Map<String, Long> tagNameIdMap = Optional.ofNullable(tagService.list(tagWrapper)).orElse(new ArrayList<>()).stream()
                    .collect(Collectors.toMap(ChararterTag::getDescribe, ChararterTag::getId,(o,n)->o));
            //更新对应原数据
            tagNameIdMap.keySet().forEach(k->{
                desIdMap.put(k,tagNameIdMap.get(k));
            });
            dto.getSrcList().forEach(s->{
                s.getItem().forEach(k->{
                    if (tagNameIdMap.containsKey(k.getDescribe())){
                        k.setId(tagNameIdMap.get(k.getDescribe()));
                    }
                });
            });

        }
        tagService.saveBatch(newTags);

        //提取图片
        List<LifePicture> pictures = new ArrayList<>();
        List<TagRelate> relates = new ArrayList<>();
        dto.getSrcList().forEach(s->{
            LifePicture picture = new LifePicture();
            picture.setPictureUrl(s.getSrc());
            picture.setId(Math.abs(UUID.randomUUID().getMostSignificantBits()));
            picture.setBelongId(lifeDay.getId());
            picture.setType("2");
            pictures.add(picture);
            s.getItem().forEach(k->{
                TagRelate relate =new TagRelate();
                Long aLong = desIdMap.get(k.getDescribe());
                if (Objects.isNull(aLong)){
                    return;
                }
                relate.setBusId(picture.getId());
                relate.setBelongType("生活记录");
                relate.setTagId(aLong);
                relates.add(relate);
            });
        });

        //保存
        pictures.add(masterPicture1);
        pictures.add(masterPicture2);
        pictureService.saveBatch(pictures);
        tagRelateService.saveBatch(relates);

        return lifeDay.getId();
    }

    @Override
    public PageResult<LifeDayListVO> daylist() {
        QueryWrapper wrapper = QueryWrapper.create().from(LifeDay.class);
        wrapper.orderBy(LifeDay::getCreateDay,false);
        PageQuery queryHand  =new PageQuery();
        queryHand.setPage(1);
        queryHand.setLimit(7);
        Page<LifeDayVO> page = pageAs(PageUtils.getPage(queryHand), wrapper, LifeDayVO.class);
        PageResult<LifeDayVO> pageResult = PageUtils.getPageResult(page);

        List<Long> lifeIds = pageResult.getRows().stream().map(LifeDayVO::getId).collect(Collectors.toList());
        //查图片
        QueryWrapper pictureWrap = QueryWrapper.create().from(LifePicture.class);
        pictureWrap.in(LifePicture::getBelongId,lifeIds);
        Set<Long> pictureIds = new HashSet<>();
        Map<Long,List<LifePicture>> lifePictureMap = Optional.ofNullable(pictureService.list(pictureWrap)).orElse(new ArrayList<>())
                .stream().peek(s->pictureIds.add(s.getId())).collect(Collectors.groupingBy(LifePicture::getBelongId));
        //查关联标签
        Set<Long> tagIds = new HashSet<>();
        QueryWrapper relativeWrap = QueryWrapper.create().from(TagRelate.class);
        relativeWrap.in(TagRelate::getBusId,pictureIds);
        Map<Long, List<TagRelate>> pictureTagMap = Optional.ofNullable(tagRelateService.list(relativeWrap)).orElse(new ArrayList<>()).stream()
                .peek(s -> tagIds.add(s.getTagId())).collect(Collectors.groupingBy(TagRelate::getBusId));
        //查标签
        QueryWrapper tagWrap = QueryWrapper.create().from(ChararterTag.class);
        relativeWrap.in(ChararterTag::getId,tagIds);
        Map<Long, ChararterTag> idTagMap = Optional.ofNullable(tagService.list(tagWrap)).orElse(new ArrayList<>()).stream()
                .collect(Collectors.toMap(ChararterTag::getId, Function.identity()));

        //累加集合
        Map<String,ChararterTagCreateDTO> mainTime = new HashMap<>();

        //组装
        List<LifeDayListVO> list = pageResult.getRows().stream().map(s -> {
            LifeDayListVO vo = new LifeDayListVO();
            vo.setId(s.getId());
            vo.setCost(s.getCost());
            vo.setHair(s.getHair());
            vo.setSki(s.getSki());
            vo.setWeight(s.getWeight());
            vo.setCreateDay(s.getCreateDay());
            vo.setExt2(s.getExt2());

            List<LifeDayCreateDTO2> dtos = new ArrayList<>();
            List<LifePicture> pictures = lifePictureMap.getOrDefault(s.getId(), new ArrayList<>());
            pictures.forEach(k -> {
                if ("0".equals(k.getType()) || "1".equals(k.getType())){
                    return;
                }
                List<TagRelate> relates = pictureTagMap.getOrDefault(k.getId(),new ArrayList<>());
                List<ChararterTagCreateDTO> tagVos = new ArrayList<>();
                relates.forEach(l -> {
                    ChararterTag tag = idTagMap.get(l.getTagId());
                    ChararterTagCreateDTO tagVo = new ChararterTagCreateDTO();
                    tagVo.setDescribe(tag.getDescribe());
                    tagVo.setColor(tag.getColor());
                    tagVo.setColorName(tag.getColorName());
                    tagVo.setId(tag.getId());
                    tagVos.add(tagVo);
                    ChararterTagCreateDTO dto = mainTime.get(tag.getDescribe());
                    if (Objects.isNull(dto)){
                        tagVo.setTime(1L);
                        mainTime.put(tag.getDescribe(),tagVo);
                    }else { 
                        dto.setTime(dto.getTime()+1);
                    }
                });
                LifeDayCreateDTO2 dto = new LifeDayCreateDTO2();
                dto.setId(k.getId());
                dto.setSrc(k.getPictureUrl());
                dto.setItem(tagVos);
                dtos.add(dto);
            });
            vo.setItem(dtos);
            //近身
            LifePicture face = lifePictureMap.getOrDefault(s.getId(), new ArrayList<>()).stream().filter(q -> "0".equals(q.getType())).findAny().orElse(new LifePicture());
            vo.setFaceUrl(face.getPictureUrl());
            //全身
            LifePicture whole = lifePictureMap.getOrDefault(s.getId(), new ArrayList<>()).stream().filter(q -> "1".equals(q.getType())).findAny().orElse(new LifePicture());
            vo.setWholeUrl(whole.getPictureUrl());

            return vo;
        }).toList();

        PageResult<LifeDayListVO> result = new PageResult<>(1, 7, 1, 7, list);
        return result;
    }

    /**
     * 更新对象
     */
    @Override
    @Transactional
    public LifeDayCreateDTO changePicture(LifeDayCreateDTO dto) {
        if (Objects.isNull(dto.getId())){
            throw new IllegalStateException("传了个空ID");
        }
        //近身
        if (StringUtils.isNotBlank(dto.getFaceUrl())) {
            QueryWrapper wrapper = QueryWrapper.create().from(LifePicture.class);
            wrapper.eq(LifePicture::getBelongId, dto.getId()).eq(LifePicture::getType, "0");
            LifePicture one = pictureService.getOne(wrapper);//有两个时会报错
            LifePictureUpdateDTO update = new LifePictureUpdateDTO();
            update.setId(one.getId());
            update.setPictureUrl(dto.getFaceUrl());
            pictureService.update(update);
            return dto;
        }
        //全身
        if (StringUtils.isNotBlank(dto.getFaceUrl())) {
            QueryWrapper wrapper = QueryWrapper.create().from(LifePicture.class);
            wrapper.eq(LifePicture::getBelongId, dto.getId()).eq(LifePicture::getType, "1");
            LifePicture one = pictureService.getOne(wrapper);//有两个时会报错
            LifePictureUpdateDTO update = new LifePictureUpdateDTO();
            update.setId(one.getId());
            update.setPictureUrl(dto.getFaceUrl());
            pictureService.update(update);
            return dto;
        }

        //30日
        //删除lifePicture relative tag保留
        QueryWrapper wrapper = QueryWrapper.create().from(LifePicture.class);
        wrapper.eq(LifePicture::getBelongId, dto.getId()).eq(LifePicture::getType, "2");
        List<Long> list = Optional.ofNullable(pictureService.list(wrapper)).orElse(new ArrayList<>()).stream().map(LifePicture::getId).toList();

        QueryWrapper relateWrapper = QueryWrapper.create().from(TagRelate.class);
        relateWrapper.in(TagRelate::getBusId, list);
        if (CollUtil.isNotEmpty(list)) {
            tagRelateService.remove(relateWrapper);
        }
        pictureService.remove(wrapper);

        //因为贫穷，所以界面禁止移除图片功能 嘿嘿嘿
        Set<String> desList = new HashSet<>();
        Map<String, Long> desIdMap = new HashMap<>();
        List<ChararterTag> newTags = dto.getSrcList()
                .stream()
                .flatMap(s -> s.getItem().stream())
                .peek(s -> {
                    if (Objects.isNull(s.getId())) {
                        return;
                    }
                    desIdMap.put(s.getDescribe(), s.getId());
                })
                .filter(s -> Objects.isNull(s.getId()))
                .map(s -> {
                    desList.add(s.getDescribe());
                    ChararterTag tag = new ChararterTag();
                    tag.setId(Math.abs(UUID.randomUUID().getMostSignificantBits()));
                    tag.setColor(s.getColor());
                    tag.setColorName(s.getColorName());
                    tag.setTagType("1");//按字典的
                    //tag.setRemark(s.getDescribe());
                    tag.setDescribe(s.getDescribe());
                    desIdMap.put(tag.getDescribe(), tag.getId());
                    return tag;
                })
                .toList();

        if (desIdMap.containsKey("") || desIdMap.containsKey(null)){
            throw new IllegalStateException("存在空标签");
        }

        QueryWrapper tagWrapper = QueryWrapper.create().from(ChararterTag.class);
        tagWrapper.in(ChararterTag::getDescribe, desList).eq(ChararterTag::getTagType, "1");//1为生活记录
        if (CollUtil.isNotEmpty(desList)){
            //throw new IllegalStateException("新的标签重复了--" + newTags.stream().map(ChararterTag::getDescribe).collect(Collectors.joining(",")));
            Map<String, Long> tagNameIdMap = Optional.ofNullable(tagService.list(tagWrapper)).orElse(new ArrayList<>()).stream()
                    .collect(Collectors.toMap(ChararterTag::getDescribe, ChararterTag::getId,(o,n)->o));
            //更新对应原数据
            tagNameIdMap.keySet().forEach(k->{
                desIdMap.put(k,tagNameIdMap.get(k));
            });
            dto.getSrcList().forEach(s->{
                s.getItem().forEach(k->{
                    if (tagNameIdMap.containsKey(k.getDescribe())){
                        k.setId(tagNameIdMap.get(k.getDescribe()));
                    }
                });
            });

        }
        tagService.saveBatch(newTags);

        //提取图片
        List<LifePicture> pictures = new ArrayList<>();
        List<TagRelate> relates = new ArrayList<>();
        dto.getSrcList().forEach(s -> {
            LifePicture picture = new LifePicture();
            picture.setPictureUrl(s.getSrc());
            picture.setId(Math.abs(UUID.randomUUID().getMostSignificantBits()));
            picture.setBelongId(dto.getId());
            picture.setType("2");
            pictures.add(picture);
            s.getItem().forEach(k -> {
                TagRelate relate = new TagRelate();
                Long aLong = desIdMap.get(k.getDescribe());
                if (Objects.isNull(aLong)) {
                    return;
                }
                relate.setBusId(picture.getId());
                relate.setBelongType("生活记录");
                relate.setTagId(aLong);
                relates.add(relate);
            });
        });
        pictureService.saveBatch(pictures);
        tagRelateService.saveBatch(relates);

        return dto;
    }

    private static QueryWrapper buildQueryWrapper(LifeDayListDTO dto) {
        QueryWrapper wrapper = QueryWrapper.create().from(LifeDay.class);
        if (Utils.isNotNull(dto.getCreateDayStart()) && Utils.isNotNull(dto.getCreateDayEnd())) {
            wrapper.between(LifeDay::getCreateDay, dto.getCreateDayStart(), dto.getCreateDayEnd());
        }
        if (Utils.isNotNull(dto.getWeight())) {
            wrapper.eq(LifeDay::getWeight, dto.getWeight());
        }
        if (Utils.isNotNull(dto.getHair())) {
            wrapper.eq(LifeDay::getHair, dto.getHair());
        }
        if (Utils.isNotNull(dto.getSki())) {
            wrapper.eq(LifeDay::getSki, dto.getSki());
        }
        if (Utils.isNotNull(dto.getCost())) {
            wrapper.eq(LifeDay::getCost, dto.getCost());
        }
        if (Utils.isNotNull(dto.getExt2())) {
            wrapper.eq(LifeDay::getExt2, dto.getExt2());
        }
        if (Utils.isNotNull(dto.getExt3())) {
            wrapper.eq(LifeDay::getExt3, dto.getExt3());
        }
        if (Utils.isNotNull(dto.getExt4())) {
            wrapper.eq(LifeDay::getExt4, dto.getExt4());
        }
        if (Utils.isNotNull(dto.getExt5())) {
            wrapper.eq(LifeDay::getExt5, dto.getExt5());
        }
        if (Utils.isNotNull(dto.getExt6())) {
            wrapper.eq(LifeDay::getExt6, dto.getExt6());
        }
        return wrapper;
    }
}